using NanoVirtualView;
using System.Diagnostics;

namespace 图片裁剪压缩工具
{
    public partial class Form1 : Form
    {
        private VirtualViewRegister register;
        private ImageManager ImageManager { get; }
        public Form1()
        {
            InitializeComponent();

            register = new VirtualViewRegister(pictureBox1);
            ImageManager = new ImageManager(pictureBox1);

            register.HostMouseClick += Register_HostMouseClick;
            rb_Free.CheckedChanged += CutTypeCheckedChanged;
            rb_ConstAspectRatio.CheckedChanged += CutTypeCheckedChanged;
            rb_ConstAspectRatioAndToAssigned.CheckedChanged += CutTypeCheckedChanged;
            rb_Assigned.CheckedChanged += CutTypeCheckedChanged;
            ImageManager.ImageChange = ImageChange;
        }
        private void ContextMenuStripItemAction(object? sender, EventArgs e)
        {
            if (Clipboard.ContainsImage())
            {
                ImageManager.Reset(Clipboard.GetImage(), true);
            }
            else
            {
                if (Clipboard.ContainsFileDropList())
                {
                    foreach (string? current in Clipboard.GetFileDropList())
                    {
                        if (current != null &&
                            (current.ToLower().EndsWith(".jpg")//
                            || current.ToLower().EndsWith(".jpeg")//
                            || current.ToLower().EndsWith(".gif")//
                            || current.ToLower().EndsWith(".png") //
                            || current.ToLower().EndsWith(".tif") //
                            || current.ToLower().EndsWith(".tiff")//
                            || current.ToLower().EndsWith(".bmp")))
                        {
                            using var input = File.OpenRead(current);
                            try
                            {
                                Image image = Image.FromStream(input);
                                ImageManager.Reset(image, true);
                            }
                            catch (Exception)
                            {
                            }
                            break;
                        }
                    }
                }
            }
        }
        private void Register_HostMouseClick(object? sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                var toolStripDropDown = new ContextMenuStrip()
                {
                    Items = { { "粘贴", null, ContextMenuStripItemAction } }
                };
                toolStripDropDown.Show(sender is VirtualViewRegister vvr ? vvr.Host : null, e.Location);
            }
        }
        private void CutTypeCheckedChanged(object? sender, EventArgs e)
        {
            register.RemoveAll();
        }

        private void ImageChange(object? o, Image? image)
        {
            register.RemoveAll();
            Text = image != null ? $"图片-{image.Width},{image.Height}" : "图片裁剪压缩工具";
        }

        private void btn_open_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "图片|*.jpeg;*.jpg;*.png;*.bmp;*.gif;*.webp";
            ofd.Multiselect = false;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string fileName = ofd.FileName;
                if (fileName.ToLower().EndsWith(".webp"))
                {
                    if (!IOUtil.Webp2Png(ofd.FileName, out fileName))
                    {
                        return;
                    }
                }
                Debug.WriteLine(fileName);
                ImageManager.Reset(Image.FromFile(fileName), true);
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            register.RemoveAll();
            ImageManager.Cancel();
        }
        public static bool Parse(string s, out int a, out int b)
        {
            a = b = 0;
            var ss = s.Split(new char[] { ',', '，' });
            return ss.Length == 2 && int.TryParse(ss[0], out a) && int.TryParse(ss[1], out b) && a > 0 && b > 0;
        }
        private void btn_save_Click(object sender, EventArgs e)
        {
            if (register.LayoutCount > 0)
            {
                MessageBox.Show("正在裁剪中，请鼠标左键双击选中区域裁剪后再保存或鼠标右键双击取消裁剪！");
                return;
            }
            if (ImageManager.Current != null)
            {
                int bestQ = 80;
                int limitSize = 10240;
                if (!int.TryParse(tb_q.Text, out bestQ) || bestQ < 10 || bestQ > 100)
                {
                    MessageBox.Show("压缩质量在10~100之间!");
                    return;
                }
                if (cb_limit.Checked && !int.TryParse(tb_limitSize.Text, out limitSize))
                {
                    MessageBox.Show("压缩限制大小输入有误，请重新输入!");
                    return;
                }
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "图片|*.jpg";
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    ImageEncoder.Encoder encoder = new ImageEncoder.Encoder(ImageManager.Current, bestQ, this.cb_size.Checked, !this.cb_q.Checked, limitSize * 1024);
                    if (encoder.Do(sfd.FileName, out var endSize, out var endQ, out var outFileSize))
                    {
                        Debug.WriteLine($"{endSize},{endQ},{outFileSize}");
                    }
                    else
                    {
                        var msg = $"无法压缩到理想状态!\n极限尺寸:{{{endSize.Width},{endSize.Height}}},质量:{endQ},{outFileSize / 1024.0:f2}K";
                        MessageBox.Show(msg);
                    }
                }
            }
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if(ImageManager.Current != null)
            {
                register.RemoveAll();
                RectView rv= new(register);
                if (rb_Free.Checked)
                {
                    rv.ChangeEventToAndChangeUI(new FreeCutEvent());
                }
                else
                {
                    if(!Parse(this.tb_destSize.Text, out var w, out var h))
                    {
                        MessageBox.Show("指定值输入有误!");
                        return;
                    }
                    if (rb_ConstAspectRatio.Checked)
                    {
                        rv.ChangeEventToAndChangeUI(new ConstAspectRatioCutEvent(w, h), new SizeF(w,h));
                    }else if (rb_ConstAspectRatioAndToAssigned.Checked)
                    {
                        rv.ChangeEventToAndChangeUI(new ConstAspectRatioCutEvent(w, h, w, h), new SizeF(w, h));
                    }
                    else if(rb_Assigned.Checked)
                    {
                        ImageDisplayInfo info = ImageDisplayInfo.GetInstance(this.pictureBox1);
                        rv.ChangeEventToAndChangeUI(new ConstSizeCutEvent(w, h), new SizeF((float)(w / info.K), (float)(h / info.K)));
                    }else
                    {
                        return;
                    }
                }
                register.AddVirtualView(rv);
                rv.MouseDoubleClick += Rv_MouseDoubleClick;

                var Rv_LocationOrSizeChanged = (object sender,RectangleF rect) =>
                { 
                    tb_selectSize.Text = $"{(int)rect.Left},{(int)rect.Top},{(int)rect.Width},{(int)rect.Height}";
                };
                rv.SizeChanged += new BaseRectView.RectEventHandler(Rv_LocationOrSizeChanged);
                rv.LocationChanged += new BaseRectView.RectEventHandler(Rv_LocationOrSizeChanged);
            }
        }

        private void Rv_MouseDoubleClick(object? sender, MouseEventArgs e)
        {
            register.RemoveAll();
            if (e.Button == MouseButtons.Left)
            {
                if (sender is RectView rectView)
                {
                    RectangleF select = GetSelectRect(rectView);
                    Debug.WriteLine(select);
                    int tw = rectView.CurrentRectEvent.TargetWidth;
                    int th = rectView.CurrentRectEvent.TargetHeight;
                    RectangleF dest = (tw != 0 && th != 0) ? new RectangleF(0f, 0f, tw, th) : default;
                    if (CutImage(select, out var bitmap, dest))
                    {
                        ImageManager.Add(bitmap);
                    }
                }
            }
        }

        public RectangleF GetSelectRect(RectView rectView)
        {
            ImageDisplayInfo info = ImageDisplayInfo.GetInstance(pictureBox1);
            RectangleF rect = rectView.Rectangle;
            float x = (float)((rect.X - info.Rectangle.X) * info.K);
            float y = (float)((rect.Y - info.Rectangle.Y) * info.K);
            float w = (float)(rect.Width * info.K);
            float h = (float)(rect.Height * info.K);
            return new RectangleF(x, y, w, h);
        }

        private bool CutImage(RectangleF cutRect, out Bitmap? bitmap, RectangleF dest = default)
        {
            if (ImageManager.Current==null)
            {
                bitmap = null;
                return false;
            }
            else
            {
                if (dest == default)
                {
                    dest = new RectangleF(0f, 0f, cutRect.Width, cutRect.Height);
                }
                bitmap = new Bitmap((int)dest.Width, (int)dest.Height);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.DrawImage(ImageManager.Current, dest, cutRect, GraphicsUnit.Pixel);
                }
                return true;
            }
        }

        private void ll_RotateLeft_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ImageManager.RotateFlip(RotateFlipType.Rotate270FlipNone);
        }

        private void ll_RotateRight_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ImageManager.RotateFlip(RotateFlipType.Rotate90FlipNone);
        }
    }
}